﻿using Microsoft.Xna.Framework;
using OTAPI;
using OTAPI.Tile;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Streams;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Terraria;
using Terraria.ID;
using TerrariaApi.Server;
using TShockAPI;

namespace TShock_IslandWar
{
    [ApiVersion(2, 1)]
    public class TShock_IslandWar : TerrariaPlugin
    {
        public override string Author => "星夜神花";
        public override string Description => "空岛战争";
        public override string Name => "TShock_IslandWar";
        public override Version Version => new Version(0, 0, 0, 1);
        public TShock_IslandWar(Main game) : base(game)
        {
        }


        private Config config;
        private DefaultWorld defaultWorld;
        private GameManager gameManager;

        public override void Initialize()
        {
            config = Config.LoadConfig();
            gameManager = new GameManager();

            TShock.Config.Settings.SaveWorldOnCrash = false;
            TShock.Config.Settings.SaveWorldOnLastPlayerExit = false;
            TShock.Config.Settings.AutoSave = false;
            TShock.Config.Settings.AnnounceSave = false;
            TShock.Config.Settings.PvPMode = "always";
            TShock.Config.Settings.RespawnSeconds = 5;
            TShock.Config.Settings.DefaultMaximumSpawns = 0;
            TShock.Config.Settings.DefaultSpawnRate = 0;

            ServerApi.Hooks.NetGetData.Register(this, Hooks_NetGetData);
            ServerApi.Hooks.GamePostInitialize.Register(this, Hooks_GamePostInitialize);
            ServerApi.Hooks.GameUpdate.Register(this, Hooks_GameUpdate);
            ServerApi.Hooks.ServerJoin.Register(this, Hooks_ServerJoin);

            TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += (TShockAPI.Hooks.PlayerPostLoginEventArgs e) =>
            {
                Commands.HandleCommand(TSPlayer.Server, "/resetplayer " + e.Player.Name + " all");
                gameManager.onlinePlayer++;
                if (gameManager.state == 0)
                {
                    e.Player.SendMessage("当前游戏未开始", Color.Yellow);
                    return;
                }
                if (gameManager.RedSpawn == false || gameManager.BlueSpawn == false)
                {
                    e.Player.SendMessage("当前有一场正在进行的游戏，请等待这一局游戏结束", Color.Yellow);
                    return;
                }
                if (gameManager.redTeam.Count > gameManager.blueTeam.Count)
                {
                    e.Player.SetTeam(GameManager.Blue);
                    e.Player.SetData("team", GameManager.Blue);
                    e.Player.Teleport(defaultWorld.blueSpawn.X * 16, (defaultWorld.blueSpawn.Y - 3) * 16);
                    e.Player.SendMessage("你被分配到了蓝队，保护好你的床", Color.Blue);
                    gameManager.blueTeam.Add(e.Player);
                }
                else
                {
                    e.Player.SetTeam(GameManager.Red);
                    e.Player.SetData("team", GameManager.Red);
                    e.Player.Teleport(defaultWorld.redSpawn.X * 16, (defaultWorld.redSpawn.Y - 3) * 16);
                    e.Player.SendMessage("你被分配到了红队，保护好你的床", Color.Red);
                    gameManager.redTeam.Add(e.Player);
                }
                e.Player.SetPvP(true);
            };

            TShockAPI.Hooks.PlayerHooks.PlayerLogout += (TShockAPI.Hooks.PlayerLogoutEventArgs e) =>
            {
                gameManager.onlinePlayer--;
                if (e.Player.GetData<int>("team") == GameManager.Red)
                {
                    gameManager.redTeam.Remove(e.Player);
                }
                if (e.Player.GetData<int>("team") == GameManager.Blue)
                {
                    gameManager.blueTeam.Remove(e.Player);
                }
                e.Player.KillPlayer();
            };
        }

        private void Hooks_ServerJoin(JoinEventArgs args)
        {
            TSPlayer player = TShock.Players[args.Who];
            if (player.Difficulty != 1)
            {
                player.Disconnect("服务器只允许以中核模式进入");
            }
        }

        private void Hooks_GameUpdate(EventArgs args)
        {
            gameManager.Update(defaultWorld);
        }

        private void Hooks_GamePostInitialize(EventArgs args)
        {
            defaultWorld = new DefaultWorld(config);
        }

        private void Hooks_NetGetData(GetDataEventArgs args)
        {
            PacketTypes packet = args.MsgID;
            TSPlayer player = TShock.Players[args.Msg.whoAmI];
            if(player.TileX <= config.LeftTop[0] || player.TileX >= config.RightBottom[0])
            {
                player.KillPlayer();
            }
            if (player.TileY >= config.LeftTop[1] || player.TileY <= config.RightBottom[1])
            {
                player.KillPlayer();
            }
            using (MemoryStream stream = new MemoryStream(args.Msg.readBuffer, args.Index, args.Length - 1))
            {
                switch (packet)
                {
                    case PacketTypes.Tile:
                        {
                            byte action = (byte)stream.ReadByte();
                            Int16 tileX = stream.ReadInt16();
                            Int16 tileY = stream.ReadInt16();
                            Vector2 position = new Vector2(tileX, tileY);
                            Int16 flag1 = stream.ReadInt16();
                            ITile tile = Main.tile[tileX, tileY];
                            if (config.AllowDestroy.Contains(tile.type))
                            {
                                break;
                            }
                            if (tile.type == 3 || tile.type == 73)
                            {
                                break;
                            }

                            if (action == 1 && tile.type == 79)
                            {
                                player.SendTileRect((short)(tileX - 5), (short)(tileY - 5), 10);
                                args.Handled = true;
                                break;
                            }

                            if (tile != null && tile.active() && tile.type == 79 && flag1 == 0)
                            {
                                if (defaultWorld.redSpawn.Distance(position) < defaultWorld.blueSpawn.Distance(position))
                                {
                                    if (player.GetData<int>("team") == GameManager.Blue)
                                    {
                                        TSPlayer.All.SendMessage("红队床已被[" + player.Name + "]破坏", Color.Blue);
                                        TSPlayer.All.SendMessage("红队玩家以无法复活", Color.Blue);
                                        gameManager.RedSpawn = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    if (player.GetData<int>("team") == GameManager.Red)
                                    {
                                        TSPlayer.All.SendMessage("蓝队床已被[" + player.Name + "]破坏", Color.Red);
                                        TSPlayer.All.SendMessage("蓝队玩家以无法复活", Color.Blue);
                                        gameManager.BlueSpawn = false;
                                        break;
                                    }
                                }
                                player.SendTileRect((short)(tileX - 5), (short)(tileY - 5), 10);

                                args.Handled = true;
                                break;
                            }
                            if (defaultWorld.DefaultTile[tileX, tileY] != null && defaultWorld.DefaultTile[tileX, tileY].active())
                            {
                                player.SendTileRect((short)(tileX - 5), (short)(tileY - 5), 10);
                                args.Handled = true;
                            }
                        }
                        break;
                    case PacketTypes.TogglePvp:
                        {
                            player.SetPvP(true);
                            args.Handled = true;
                        }
                        break;
                    case PacketTypes.PlayerTeam:
                        {
                            player.SetTeam(player.GetData<int>("team"));
                            args.Handled = true;
                        }
                        break;
                    case PacketTypes.DeadPlayer:
                        {
                            if (gameManager.RedSpawn == false && player.GetData<int>("team") == GameManager.Red)
                            {
                                gameManager.redTeam.Remove(player);
                                TSPlayer.All.SendMessage("玩家:[" + player.Name + "]被淘汰，红队还剩" + gameManager.redTeam.Count + "名玩家", Color.Yellow);
                            }
                            if (gameManager.BlueSpawn == false && player.GetData<int>("team") == GameManager.Blue)
                            {
                                gameManager.blueTeam.Remove(player);
                                TSPlayer.All.SendMessage("玩家:[" + player.Name + "]被淘汰，蓝队还剩" + gameManager.redTeam.Count + "名玩家", Color.Yellow);
                            }
                        }
                        break;
                    case PacketTypes.PlayerSpawn:
                        {
                            Main.spawnTileX = (int)defaultWorld.defalueSpawn.X;
                            Main.spawnTileY = (int)defaultWorld.defalueSpawn.Y;
                            if (player.Active && player.IsLoggedIn && player.ContainsData("team") && gameManager.state == 1)
                            {
                                int team = player.GetData<int>("team");
                                if (team == GameManager.Red)
                                {
                                    if (gameManager.RedSpawn)
                                    {
                                        Main.spawnTileX = (int)defaultWorld.redSpawn.X;
                                        Main.spawnTileY = (int)defaultWorld.redSpawn.Y;
                                    }
                                    else
                                    {
                                        gameManager.redTeam.Remove(player);
                                        player.SendMessage("因为你的床已被破坏，你无法复活", Color.DarkRed);
                                    }
                                }
                                if (team == GameManager.Blue)
                                {
                                    if (gameManager.BlueSpawn)
                                    {
                                        Main.spawnTileX = (int)defaultWorld.blueSpawn.X;
                                        Main.spawnTileY = (int)defaultWorld.blueSpawn.Y;
                                    }
                                    else
                                    {
                                        gameManager.blueTeam.Remove(player);
                                        player.SendMessage("因为你的床已被破坏，你无法复活", Color.DarkRed);
                                    }
                                }
                            }
                            break;
                        }
                }

            }
        }
    }
}
